﻿using System;
using System.Collections.Generic;
using System.Text;

namespace VGS {
    /// <summary>
    /// Enum specifying the different states a Set can have
    /// </summary>
    public enum SetStatus {
        SET_WARMUP,
        SET_STARTED,
        SET_ENDED
    }

    public delegate void SetResetedEventHandler(object sender);

    /// <summary>
    /// The Set class contains all necessary information for a Set
    /// </summary>
    public class Set {
        // Lineups
        private Lineups lineups = new Lineups(); // The team lineups
        private SetPoints points = null; // Collection of points
        private DateTime start_time; // Start time for the set
        private DateTime end_time; // End time
        private SetStatus set_status = SetStatus.SET_WARMUP;
        private TeamEnum? winner; // Set winner
        private int setNr; // The set's number

        // Events
        public SetResetedEventHandler SetReseted;
        //public event SetResetedEventHandler SetReseted;

        #region Properties
        /// <summary>
        /// Gets the lineups
        /// </summary>
        public Lineups Lineups {
            get {
                return lineups;
            }
        }


        /// <summary>
        /// Gets the set's number
        /// </summary>
        public int Number {
            get {
                return setNr;
            }
        }


        /// <summary>
        /// Gets the set points
        /// </summary>
        /// <exception cref="InvalidOperationException">The set has not yet been started</exception>
        public SetPoints Points {
            get {
                if (set_status != SetStatus.SET_WARMUP) {
                    return points;
                }

                throw new InvalidOperationException("The set has not yet been started");
            }
        }


        /// <summary>
        /// Gets the winner, returns TEAM_NONE in case the set hasn't (yet) got a winner
        /// </summary>
        public TeamEnum? Winner
        {
            get
            {
                return winner;
            }
        }

        /// <summary>
        /// Gets the sets status.
        /// SET_WARMUP,
        /// SET_STARTED, or
        /// SET_ENDED
        /// </summary>
        public SetStatus Status {
            get {
                return set_status;
            }
        }


        /// <summary>
        /// Returns the start time
        /// </summary>
        /// <exception cref="InvalidOperationException">If the set hasn't started</exception>
        public DateTime StartTime {
            get {
                // If the set hasn't started, the start_time is not set
                if (set_status == SetStatus.SET_WARMUP)
                    throw new InvalidOperationException("The set has not started");

                return start_time;
            }
        }

        /// <summary>
        /// Returns the end time
        /// </summary>
        /// <exception cref="InvalidOperationException">If the set hasn't started/ended</exception>
        public DateTime EndTime {
            get {
                if (set_status == SetStatus.SET_ENDED)
                    return end_time;

                throw new InvalidOperationException("The set has not ended");
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Constructor takes one argument which specifies the set's number
        /// </summary>
        /// <param name="nr">The set's number</param>
        public Set(int nr) {
            winner = null;
            setNr = nr;
        }


        /// <summary>
        /// Resets a current set. Changes Status back to SET_WARMUP,
        /// removes all points, resets winner, start and end time and
        /// lineups.
        /// </summary>
        public void Reset()
        {
            VolleyMatch vm = VolleyMatch.Instance;

            points = null;
            set_status = SetStatus.SET_WARMUP;
            winner = null;
            lineups.AwayTeam.Clear();
            lineups.HomeTeam.Clear();

            // Remove associated stats
            foreach (Player p in vm.HomeTeam.Players)
            {
                p.Stats.Remove(setNr);
            }
            foreach (Player p in vm.AwayTeam.Players)
            {
                p.Stats.Remove(setNr);
            }

            SetReseted(this);
            //StatusChanged(this, set_status);
        }


        /// <summary>
        /// Starts the set
        /// </summary>
        /// <exception cref="InvalidOperationException">Set has already been started</exception>
        public void Start(TeamEnum starts_serving) {
            if (set_status != SetStatus.SET_WARMUP)
                throw new InvalidOperationException("Set has already been started");

            VolleyMatch vm = VolleyMatch.Instance;

            set_status = SetStatus.SET_STARTED;
            points = new SetPoints(starts_serving);
            start_time = DateTime.Now;

            if (starts_serving == TeamEnum.HOME_TEAM)
                Log.Instance.AddMessage(string.Format("The set has started and {0} starts serving",
                    vm.HomeTeam.Name));
            else if (starts_serving == TeamEnum.AWAY_TEAM)
                Log.Instance.AddMessage(string.Format("The set has started and {0} starts serving",
                    vm.AwayTeam.Name));

            //StatusChanged(this, new SetEventArgs(SetStatus.SET_STARTED, this));
        }


        /// <summary>
        /// Ends the set
        /// </summary>
        /// <exception cref="InvalidOperationException">If the set hasn't started or already has ended</exception>
        public void End() {
            if (set_status == SetStatus.SET_WARMUP)
                throw new InvalidOperationException("The set has not yet started");
            if (set_status == SetStatus.SET_ENDED)
                throw new InvalidOperationException("The set has already ended");

            VolleyMatch vm = VolleyMatch.Instance;

            set_status = SetStatus.SET_ENDED;
            end_time = DateTime.Now;

            // winner indicates that the set is finished
            if (points.HomeTeamScore > points.AwayTeamScore)
                winner = TeamEnum.HOME_TEAM;
            else if (points.AwayTeamScore > points.HomeTeamScore)
                winner = TeamEnum.AWAY_TEAM;
            // This should never occur in a real game
            else winner = null;

            Log.Instance.AddMessage(string.Format("Set {0} between {1} - {2} has ended with the score {3}",
                setNr, vm.HomeTeam.Name, vm.AwayTeam.Name, points.ToString()));

            //StatusChanged(this, new SetEventArgs(SetStatus.SET_ENDED, this));
        }
        #endregion
    }
}
